from byubit import Bit
@Bit.run_from_empty(5, 3)
def go(bit):
while bit.front_clear():
bit.move()
bit.paint('green')
In this example, go
is a function.
We define functions using the def
keyword.
def
¶go_green.py
¶def go_green(bit):
while bit.front_clear():
bit.move()
bit.paint('green')
go_green
is the function namebit
is the function argument or parameterwhile
or if
block)go_green(bit)
from byubit import Bit
def go_green(cosmo):
while cosmo.front_clear():
cosmo.move()
cosmo.paint('green')
@Bit.run_from_empty(4, 3)
def go(bit):
go_green(bit)
bit.left()
go_green(bit)
go
, we use bit
to refer to Bitgo_green
we use cosmo
to refer to whatever was passed to itbit
to go_green
, cosmo
became another name for bit
NOTES
go
and the scope of go_green
bit
points to something on the heap (a bit world)go_green
is called, cosmo
now points to that same thing on the heapbit
in go_green
is different than bit
in go
bit
is good, cosmo
not so much, thing
even worse, color
worse still.from byubit import Bit
def go_green(bit):
while bit.front_clear():
bit.move()
bit.paint('green')
@Bit.run_from_empty(4, 3)
def go(bit):
go_green
bit.left()
go_green
NOTES
Didn't invoke the function: missing parentheses
from byubit import Bit
def go_green(bit):
while bit.front_clear():
bit.move()
bit.paint('green')
@Bit.run_from_empty(4, 3)
def go(bit):
go_green()
bit.left()
go_green()
NOTES
Missing positional argument. The name the error gives you is the name of the parameter in the function you tried to call.
How can we figure out where the problem was? For example, was it the first or second call to go_green
?
In coming weeks, we'll talk about other tools that make this easier in complex programs.
For now, you can use bit.snapshot
to put breadcrumbs in the program to figure out where the problem is happening.
When naming a function:
_
(next to the zero key + shift) to break up compound namesgo_green
instead of gogreen
or goGreen
go
instead of Go
or GO
go
is different from Go
!from byubit import Bit
def go_green(bit):
"""
Bit moves in the direction it is already facing
and goes until it is blocked in front
Bit paints each square green,
except for the starting square
"""
while bit.front_clear():
bit.move()
bit.paint('green')
@Bit.run_from_empty(4, 3)
def go(bit):
go_green(bit)
bit.left()
go_green(bit)
"""
allow us to include multiple lines in the same string.snapshot_demo.py
¶NOTES
Gordon Bean:
When our oldest child was just learning how to crawl, my wife and I discovered that our daughter would often get right up behind us without us realizing it. When we would turn around to move to another activity, we would stumble over her. It wasn't a great setup. We were often warning each other that there was a baby right behind. So one day my wife declared: "We need a code word we can use to say 'be careful turning around: there is a baby right behind you'" I agreed that was a good idea, and after a moment's thought she declared "jellyfish".
So, for several years, we've used the term jellyfish to communicate "watch out, there is someone/something right behind you that you might run into as you turn around". It's become second nature. So much, in fact, that I almost used it with a colleague one day as I navigated a crowded room and was passing right behind her.
Human beings have a natural ability for creating ideas ("watch out for the baby right behind you") and giving them names ("jellyfish").
Defining functions is just like that. We get to come up with the idea we want and name it. Then we can use it just like it is an ordinary word.
NOTES
The concept of creating and naming new ideas is called abstraction
Bit gives us move
, paint
, etc.
What new verbs would make this job even easier?
NOTES
We've done problems like this before (nested while, etc.), but this is the first time we are using functions to define the pieces. The emphasis of this exercise is on the decomposition and abstraction of the parts, and then putting those parts together.
Several strategies to consider:
Which seems easiest? Why?
Activity
go
using fill_row_with_blue(bit)
(even though it isn't defined yet)Then define and implement fill_row_with_blue
What are the boundary conditions of fill_row_with_blue
?
# Solution
from byubit import Bit
def go(bit):
while bit.front_clear():
bit.move()
def go_blue(bit):
bit.paint('blue')
while bit.front_clear():
bit.move()
bit.paint('blue')
def turn_around(bit):
bit.left()
bit.left()
def fill_column_with_blue(bit):
"""
Bit starts facing up
Bit turns right and fills the row with blue
Bit returns to the left and turns to face up
"""
bit.left()
go_blue(bit)
turn_around(bit)
go(bit)
bit.left()
@Bit.run_from_empty(6, 6)
@Bit.pictures('images/')
def run(bit):
fill_column_with_blue(bit)
while bit.front_clear():
bit.move()
fill_column_with_blue(bit)
turn_around(bit)
go(bit)
turn_around(bit)
NOTES
The event stream pattern works well: the event is running into a jumpable wall (left clear). The event loop runs until Bit cannot jump anymore.
if/else
as opposed to a single "jump hurdle" eventThe mosaic pattern could work: move to the base of the first hurdle, then jump hurdles (which includes advancing to the next) until left is not clear.
Approach this using the event-stream pattern, instead of the mosaic pattern used by Stanford
Note that "up" and "over" are similar, vs "down"
# solution
from byubit import Bit
def go_green(bit):
"""
Bit moves forward until blocked, painting green on the way
The first square is not painted; the last square IS painted.
"""
while bit.front_clear():
bit.move()
bit.paint('green')
def cover_green(bit):
"""
Bit moves forward until the right side is clear, painting green on the way
The first square is not painted; the last square IS painted.
"""
while not bit.right_clear():
bit.move()
bit.paint('green')
def jump_hurdle(bit):
"""
Bit starts at base of hurdle on left side facing right
Bit ends at base of hurdle on right side facing right
"""
# Up
bit.left()
cover_green(bit)
bit.right()
# Over
bit.move()
bit.paint('green')
cover_green(bit)
# Down
bit.right()
go_green(bit)
bit.left()
@Bit.run('hurdles', 'more-hurdles')
@Bit.pictures('images/')
def run(bit):
bit.paint('green')
while bit.left_clear():
if bit.front_clear():
bit.move()
bit.paint('green')
# go_green(bit)
else:
jump_hurdle(bit)
# another solution
from byubit import Bit
def jump(bit):
bit.left()
while not bit.right_clear():
bit.move()
bit.paint('green')
bit.right()
bit.move()
bit.paint('green')
def fall(bit):
bit.right()
while bit.front_clear():
bit.move()
bit.paint('green')
bit.left()
@Bit.run('hurdles', 'more-hurdles')
def run(bit):
bit.paint('green')
while bit.left_clear():
if bit.right_clear():
fall(bit)
elif not bit.front_clear():
jump(bit)
else:
bit.move()
bit.paint('green')
def